﻿using AuthTemplate.Repository.Interface;
using MySql.Data.MySqlClient;
using System;
using System.Collections.Generic;
using System.Data.Common;
using System.Data.Entity;
using System.Data.Entity.Infrastructure;
using System.Data.SqlClient;
using System.Linq;
using System.Linq.Expressions;
using System.Text;
using System.Threading.Tasks;

namespace AuthTemplate.Repository.Repositories
{
    public class BaseRepository<T> : IRepository<T> where T : class
    {
        private DbContext dataContext;

        #region Properties
        protected IDbFactory DbFactory
        {
            get;
            private set;
        }

        protected DbContext DbContext
        {
            get { return dataContext ?? (dataContext = DbFactory.Init()); }
        }
        public BaseRepository(IDbFactory dbFactory)
        {
            DbFactory = dbFactory;
        }
        #endregion

        public virtual DbContext GetDbContext()
        {
            return DbContext;
        }
        public virtual IQueryable<T> GetAll()
        {
            return DbContext.Set<T>();
        }
        public virtual IQueryable<T> All
        {
            get
            {
                return GetAll();
            }
        }
        public virtual IQueryable<T> AllIncluding(params Expression<Func<T, object>>[] includeProperties)
        {
            IQueryable<T> query = DbContext.Set<T>();
            foreach (var includeProperty in includeProperties)
            {
                query = query.Include(includeProperty);
            }
            return query;
        }
        public T GetSingle()
        {
            return GetAll().FirstOrDefault();
        }
        public virtual IQueryable<T> FindBy(Expression<Func<T, bool>> predicate)
        {
            return DbContext.Set<T>().Where(predicate).AsNoTracking();
        }

        public virtual void Add(T entity)
        {
            DbEntityEntry dbEntityEntry = DbContext.Entry<T>(entity);
            DbContext.Set<T>().Add(entity);
        }
        public virtual void Edit(T entity)
        {
            DbEntityEntry dbEntityEntry = DbContext.Entry<T>(entity);
            dbEntityEntry.State = EntityState.Modified;
        }

        public virtual void Edit(T entity, params string[] parameters)
        {
            DbEntityEntry dbEntityEntry = DbContext.Entry<T>(entity);
            dbEntityEntry.State = EntityState.Unchanged;
            foreach(var param in parameters)
            {
                dbEntityEntry.Property(param).IsModified = true;
            }
        }

        /// <summary>
        /// 分离依存的实体对象
        /// </summary>
        /// <param name="entity"></param>
        /// <returns></returns>
        public bool DetachExistsEntity(T entity)
        {
            DbEntityEntry dbEntityEntry = DbContext.Entry<T>(entity);
            dbEntityEntry.State = EntityState.Detached;
            return true;
        }

        public virtual void Delete(T entity)
        {
            DbEntityEntry dbEntityEntry = DbContext.Entry<T>(entity);
            dbEntityEntry.State = EntityState.Deleted;
        }

        public int ExecuteSqlCommand(string sql, params object[] parameters)
        {

            return DbContext.Database.ExecuteSqlCommand(sql, parameters);   
        }



        public List<S> SqlQueryList<S>(string sql, params object[] parameters)
        {

            return DbContext.Database.SqlQuery<S>(sql, parameters).ToList();
                
        }

        public S SqlQuery<S>(string sql, params object[] parameters)
        {

            return DbContext.Database.SqlQuery<S>(sql, parameters).FirstOrDefault();
                
        }
    }
}

